package com.tianxiabuyi.persist;

/**
 * Created by yang on 2017/3/25.
 */
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.Transaction;

/**
 * 本类主要提供添加和修改方法，addItem和modItem具体参数在方法描述中<br>
 * DBTools.db("basedb").addItem();<br>
 * DBTools.db("basedb").modItem();<br>
 * @author yangh
 *
 */
public class DBTools {
    // 数据源名称和DBTools
    private static HashMap<String, DBTools> dbs = new HashMap<String, DBTools>();
    // 一个DataSource代表一个数据源
    private DataSource dataSource;

    /**
     * 构造方法,保证对象只能从dbs里获取
     */
    private DBTools() {
    }

    /**
     * 重新设置数据源，包括映射文件的重新读取(一般用于修改了数据库字段后，不重启服务器)
     */
    public static void resetDbs() {
        DataSource.resetDataSources();
        dbs.clear();
    }

    /**
     * 获取当前对象的SessionFactory
     */
    public SessionFactory getSf() {
        return this.dataSource.getSf();
    }

    /**
     * 根据数据源名称获取SessionFactory
     */
    public static SessionFactory getSf(String dbName) {
        return DBTools.db(dbName).dataSource.getSf();
    }

    /**
     * 根据数据源名称获取DBTools对象
     */
    public static DBTools db(String dbName) {
        if (null == dbName)
            throw new NullPointerException("dbName为空");

        DBTools tools = dbs.get(dbName);
        if (tools == null) {
            tools = new DBTools();
            tools.dataSource = DataSource.getDataSource(dbName);
            dbs.put(dbName, tools);
        }
        return tools;
    }

    /**
     * 根据对象删除
     * @param classDesc 对象类型
     * @param key 要删除的记录主键
     */
    public void delItem(Class<?> classDesc, Serializable key) {
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Transaction ta = ss.beginTransaction();
            ss.delete(ss.get(classDesc, key));
            ta.commit();
            ss.close();
        } catch (Exception ex) {
            ss.close();
            ex.printStackTrace();
        }
    }

    /**
     * 根据map删除
     * @param mapName 数据库表对应的映射名
     * @param key 要删除的记录主键
     */
    public void delItem(String mapName, Serializable key) {
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Transaction ta = ss.beginTransaction();
            ss.createQuery("delete from " + mapName + " where id=" + key)
                    .executeUpdate();
            ta.commit();
            ss.close();
        } catch (Exception ex) {
            ss.close();
            ex.printStackTrace();
        }
    }

    /**
     * 根据对象添加
     * @param item 要添加的对象
     * @return 添加成功后的记录主键
     */
    public Serializable addItem(Object item) {
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Transaction ta = ss.beginTransaction();
            Serializable key = ss.insert(item);
            ta.commit();
            ss.close();
            return key;
        } catch (Exception ex) {
            ss.close();
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * 根据容器添加
     * @param mapName 表对应的映射名
     * @param mapValue 要添加的容器
     * @return
     */
    @SuppressWarnings("rawtypes")
    public Serializable addItem(String mapName, Map mapValue) {
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Transaction ta = ss.beginTransaction();
            Serializable key = ss.insert(mapName, mapValue);
            ta.commit();
            ss.close();
            return key;
        } catch (Exception ex) {
            ss.close();
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * 根据容器批量添加
     * @param mapName
     * @param list
     * @return
     */
    @SuppressWarnings("rawtypes")
    public List<Integer> addItem(String mapName, List<Map> list) {
        List<Integer> idList = new ArrayList<Integer>();
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Transaction ta = ss.beginTransaction();
            for (int i = 0; i < list.size(); i++) {
                Map mapValue = list.get(i);
                Serializable key = ss.insert(mapName, mapValue);
                idList.add((Integer) key);
            }

            ta.commit();
            ss.close();
        } catch (Exception ex) {
            idList.clear();
            ss.close();
            ex.printStackTrace();
        }
        return idList;
    }

    /**
     * 根据容器批量添加
     */
    public List<Integer> addItem(List list) {
        List<Integer> idList = new ArrayList<Integer>();
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Transaction ta = ss.beginTransaction();
            for (int i = 0; i < list.size(); i++) {
                Object object = list.get(i);
                Serializable key = ss.insert(object);
                idList.add((Integer) key);
            }

            ta.commit();
            ss.close();
        } catch (Exception ex) {
            idList.clear();
            ss.close();
            ex.printStackTrace();
        }
        return idList;
    }

    /**
     * 根据容器批量修改
     * @param mapName
     * @param list
     */
    @SuppressWarnings("rawtypes")
    public void modItem(String mapName, List<Map> list) {
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Transaction ta = ss.beginTransaction();
            for (int i = 0; i < list.size(); i++) {
                Map mapValue = list.get(i);
                ss.update(mapName, mapValue);
            }

            ta.commit();
            ss.close();
        } catch (Exception ex) {
            ss.close();
            ex.printStackTrace();
        }
    }

    /**
     * 根据容器修改
     */
    @SuppressWarnings("rawtypes")
    public void modItem(String mapName, Map mapValue) {
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Transaction ta = ss.beginTransaction();
            ss.update(mapName, mapValue);
            ta.commit();
            ss.close();
        } catch (Exception ex) {
            ss.close();
            ex.printStackTrace();
        }
    }

    /**
     * 根据对象修改
     */
    public void modItem(Object item, Serializable key) {
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Object old = ss.get(item.getClass(), key);
            PersistTools.modItem(old, item);
            Transaction ta = ss.beginTransaction();
            ss.update(old);
            ta.commit();
            ss.close();
        } catch (Exception ex) {
            ss.close();
            ex.printStackTrace();
        }
    }

    /**
     * 根据对象修改
     */
    public void modItem(List list) {
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        try {
            Transaction ta = ss.beginTransaction();
            for (int i =0; i < list.size(); i++) {
                Object object = list.get(i);
                Class<?> classz = object.getClass();
                Method method = classz.getMethod("getId");
                Object old = ss.get(object.getClass(), (Integer)method.invoke(object));
                PersistTools.modItem(old, object);
                ss.update(old);
            }
            ta.commit();
            ss.close();
        } catch (Exception ex) {
            ss.close();
            ex.printStackTrace();
        }
    }

    @SuppressWarnings("rawtypes")
    public CommonResult<List> query(String hql, Integer itemCount,
                                    Integer pageNum) {
        String countHql = "select count(*) " + hql;
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        Transaction ta = ss.beginTransaction();

        Query query = ss.createQuery(hql);
        if ((itemCount != null) && (itemCount > 0)) {
            if ((pageNum != null) && (pageNum > 0)) {
                query.setFirstResult((pageNum - 1) * itemCount).setMaxResults(
                        itemCount);
            }
        }
        List list = query.list();
        Long count = (Long) (ss.createQuery(countHql).list()).get(0) + 0l;
        ta.commit();
        ss.close();
        CommonResult<List> result = new CommonResult<List>();
        result.extInfo.put("count", count);
        result.setResultObj(list);
        return result;
    }

    @SuppressWarnings("rawtypes")
    public CommonResult<List> query(String hql, String countHql,
                                    Integer itemCount, Integer pageNum) {
        StatelessSession ss = this.dataSource.getSf().openStatelessSession();
        Query query = ss.createQuery(hql);
        if ((itemCount != null) && (itemCount > 0)) {
            if ((pageNum != null) && (pageNum > 0)) {
                query.setFirstResult((pageNum - 1) * itemCount).setMaxResults(
                        itemCount);
            }
        }
        List list = query.list();
        Long count = (Long) (ss.createQuery(countHql).list()).get(0) + 0l;
        ss.close();
        CommonResult<List> result = new CommonResult<List>();
        result.extInfo.put("count", count);
        result.setResultObj(list);
        return result;
    }
}